package com.imdroid.carac.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;

import com.baidu.location.BDLocation;
import com.imdroid.carac.IMDroid;
import com.imdroid.carac.R;
import com.imdroid.carac.activities.MemberListActivity;

/**
 * The modal of team
 * 
 */
public class Team {
	/**
	 * The code of team leader
	 */
	public static int ROLE_LEADER = 1;
	/**
	 * The code of team member
	 */
	public static int ROLE_MEMBER = 2;
	/**
	 * The current team
	 */
	private static Team currentTeam;
	/**
	 * The id of the team
	 */
	private int teamId;
	/**
	 * The id of the team
	 */
	private String teamName;
	/**
	 * The leader of the team
	 */
	private TeamMember teamLeader;
	/**
	 * The name of Destination
	 */
	private String destinationName;
	/**
	 * The lat of Destination
	 */
	private float destinationLat;
	/**
	 * The lat of Destination
	 */
	private float destinationLon;
	/**
	 * If need to search the route when setting the destination
	 */
	private boolean searchRoute;
	/**
	 * The source of the team
	 */
	private int teamSource;
	/**
	 * The code of the team source
	 */
	public final static int SOURCE_ME = 0;
	public final static int SOURCE_HISTORY = 1;
	public final static int SOURCE_SEARCH = 2;
	public final static int SOURCE_NEARBY = 3;

	/**
	 * Team Member list
	 */
	@SuppressLint("UseSparseArrays")
	private Map<Integer, TeamMember> members = // new HashMap<Integer,
												// TeamMember>();
	new MemberListActivity.MemberMap<Integer, TeamMember>();

	/**
	 * Get the current team
	 * 
	 * @return the currentTeam
	 */
	public static Team getCurrentTeam() {
		return currentTeam;
	}

	/**
	 * Sewt the current team
	 * 
	 * @param currentTeam
	 *            the currentTeam to set
	 */
	public static void setCurrentTeam(Team arg0) {
		currentTeam = arg0;
	}

	/**
	 * Get the id of the team
	 * 
	 * @return the teamId
	 */
	public int getTeamId() {
		return teamId;
	}

	/**
	 * Set the id of the team.
	 * 
	 * @param teamId
	 *            the teamId to set
	 */
	public void setTeamId(int teamId) {
		this.teamId = teamId;
	}

	/**
	 * Get the team name
	 * 
	 * @return the teamName
	 */
	public String getTeamName() {
		return teamName;
	}

	/**
	 * Set the team name
	 * 
	 * @param teamName
	 *            the teamName to set
	 */
	public void setTeamName(String teamName) {
		this.teamName = teamName;
	}

	/**
	 * Get the leader of the team
	 * 
	 * @return the teamLeader
	 */
	public TeamMember getTeamLeader() {
		return teamLeader != null ? teamLeader : members.get(getTeamId());
	}

	/**
	 * Set the leader of the team
	 * 
	 * @param teamLeader
	 *            the teamLeader to set
	 */
	public void setTeamLeader(TeamMember teamLeader) {
		this.teamLeader = teamLeader;
	}

	/**
	 * Set the name of destination
	 * 
	 * @return the destinationName
	 */
	public String getDestinationName() {
		return destinationName;
	}

	/**
	 * Get the name of destination
	 * 
	 * @param destinationName
	 *            the destinationName to set
	 */
	public void setDestinationName(String destinationName) {
		this.destinationName = destinationName;
	}

	/**
	 * Get the lat of destination
	 * 
	 * @return the destinationLat
	 */
	public float getDestinationLat() {
		return destinationLat;
	}

	/**
	 * set the lat of destination
	 * 
	 * @param destinationLat
	 *            the destinationLat to set
	 */
	public void setDestinationLat(float destinationLat) {
		this.destinationLat = destinationLat;
	}

	/**
	 * Get the lon of getDestinatioLon
	 * 
	 * @return the destinatioLon
	 */
	public float getDestinationLon() {
		return destinationLon;
	}

	/**
	 * Set the lon of getDestinatioLon
	 * 
	 * @param destinatioLon
	 *            the destinatioLon to set
	 */
	public void setDestinationLon(float destinatioLon) {
		this.destinationLon = destinatioLon;
	}

	/**
	 * Get the team source
	 * 
	 * @return the teamSource
	 */
	public int getTeamSource() {
		return teamSource;
	}

	/**
	 * Set the team source
	 * 
	 * @param teamSource
	 *            the teamSource to set
	 */
	public void setTeamSource(int teamSource) {
		this.teamSource = teamSource;
	}

	/**
	 * Get if need to search route when setting the destination
	 * 
	 * @return the searchRoute
	 */
	public boolean isSearchRoute() {
		return searchRoute;
	}

	/**
	 * Set if need to search route when setting the destination
	 * 
	 * @param searchRoute
	 *            the searchRoute to set
	 */
	public void setSearchRoute(boolean searchRoute) {
		this.searchRoute = searchRoute;
	}

	/**
	 * Get my old in the team
	 * 
	 * @return the myRole
	 */
	public int getMyRole() {
		return (IMDroid.getUser().getUser_id() == teamId) ? ROLE_LEADER
				: ROLE_MEMBER;
	}

	/**
	 * Add the team member
	 * 
	 * @param teamMember
	 *            the member of the team
	 */
	public void addTeamMember(TeamMember teamMember) {
		members.put(teamMember.getId(), teamMember);
	}

	/**
	 * Add the team member
	 * 
	 * @param teamMember
	 *            the member of the team
	 */
	public void removeTeamMember(TeamMember teamMember) {
		if (members.containsKey(teamMember.getId()))
			members.remove(teamMember.getId());
	}

	/**
	 * Get a new team from the http message
	 * 
	 * @param httpMessage
	 *            http message
	 * @return the new member object from the http message
	 */
	public static Team getTeam(String httpMessage) {
		Team team = new Team();

		String[] item = httpMessage.split(":");
		team.setTeamId(Integer.parseInt(item[0]));
		team.setTeamName(item[1]);
		return team;
	}

	/**
	 * Get the members
	 * 
	 * @return the members
	 */
	public Map<Integer, TeamMember> getMembers() {
		return members;
	}

	/**
	 * Set the members
	 * 
	 * @param members
	 *            the members to set
	 */
	public void setMembers(Map<Integer, TeamMember> members) {
		this.members = members;
	}

	/**
	 * Get the text of the members
	 * 
	 * @param myLocation
	 *            the location of me
	 * @return the text of the members
	 */
	public String getAllMemberText(BDLocation myLocation) {
		List<Map.Entry<Double, String>> mappingList = null;
		Map<Double, String> map = new HashMap<Double, String>();
		String strNameMyselft = IMDroid.getUser().getUser_name();
		String strNameTeamLeader = "";
		String strDistTeamLeader = "";

		for (TeamMember member : members.values()) {
			StringBuffer text = new StringBuffer();

			if (member.getId() == getTeamId())
				text.append("<font color='red'>");
			else
				text.append("<font color='blue'>");

			if (member.getId() == IMDroid.getUser().getUser_id()) {
				strNameMyselft = member.getDisplayName();
				continue;// 自己暂时不参与排序，因为在后面统一处理
			}

			text.append(member.getDisplayName());
			text.append(" (");

			double ddist = 0;
			String speed = "";
			String sdist = "";
			if (myLocation != null && member.getLat() != 0
					&& member.getLon() != 0) {

				ddist = getDistance(myLocation.getLatitude(),
						myLocation.getLongitude(), member.getLat(),
						member.getLon());

				sdist = (ddist >= 1000) ? Math.round(ddist / 1000)
						+ IMDroid.getContext().getString(
								R.string.team_map_kilometer) : Math
						.round(ddist)
						+ IMDroid.getContext().getString(
								R.string.team_map_meter);

				// 如果超过1米/秒，则显示公里/小时，否则显示
				speed = "";
				if (member.getSpeed() > 1)
					speed = Math.round(member.getSpeed() * 3.6)
							+ IMDroid.getContext().getString(
									R.string.team_map_speed_1);
				else
					speed = Math.round(member.getSpeed() * 3600)
							+ IMDroid.getContext().getString(
									R.string.team_map_speed_2);

				text.append(sdist + "," + speed + "");

			} else {
				text.append("....");
			}
			text.append(")");
			text.append("</font><br>");
			if (member.getId() == getTeamId()) {
				strNameTeamLeader = member.getDisplayName();
				strDistTeamLeader = sdist + "," + speed + "";
				// 如果 是队长，则先跳过，后面再处理
			} else {
				map.put(ddist, text.toString());
			}
		}

		mappingList = new ArrayList<Map.Entry<Double, String>>(map.entrySet());
		Collections.sort(mappingList,
				new Comparator<Map.Entry<Double, String>>() {
					public int compare(Map.Entry<Double, String> mapping1,
							Map.Entry<Double, String> mapping2) {
						return mapping1.getKey().compareTo(mapping2.getKey());
					}
				});

		StringBuffer text = new StringBuffer();
		text.append("<br>");
		int j = 0;
		// 如果自己是队长，队长与自己合二为一
		if (IMDroid.getUser().getUser_id() == getTeamId()) {
			text.append("<font color='red'>");
			text.append(1 + "." + strNameMyselft);
			text.append("</font><br>");
			j = 2;
		} else {
			// 如果两者不统一时，首先加上队长的位置，然后才是加上自己的位置
			// 先加上队长
			text.append("<font color='red'>");
			text.append(1 + "." + strNameTeamLeader + ":" + strDistTeamLeader);
			text.append("</font><br>");
			// 再加上自己
			text.append("<font color='blue'>");
			text.append(2 + "." + strNameMyselft);
			text.append("</font><br>");

			j = 3;
		}

		for (Map.Entry<Double, String> mapping : mappingList) {
			text.append(j + "." + mapping.getValue());
			++j;
		}

		return text.toString();
	}

	/**
	 * Get the text of the specfic members
	 * 
	 * @param myLocation
	 *            the location of me
	 * @param userId
	 *            the target user id
	 * @return the text of the members
	 */
	public String getMemberText(BDLocation myLocation, int userId) {
		//int i = 1;
		StringBuffer text = new StringBuffer();
		TeamMember member = members.get(userId);
		if (member == null)
			return "";
		text.append(member.getDisplayName());
		text.append(" (");

		if (myLocation != null && member.getLat() != 0 && member.getLon() != 0) {
			double ddist = getDistance(myLocation.getLatitude(),
					myLocation.getLongitude(), member.getLat(), member.getLon());
			String sdist = (ddist >= 1000) ? Math.round(ddist / 1000)
					+ IMDroid.getContext().getString(
							R.string.team_map_kilometer) : Math.round(ddist)
					+ IMDroid.getContext().getString(R.string.team_map_meter);

			// 如果超过1米/秒，则显示公里/小时，否则显示
			String speed = "";
			if (member.getSpeed() >= 1)
				speed = Math.round(member.getSpeed() * 3.6)
						+ IMDroid.getContext().getString(
								R.string.team_map_speed_1);
			else
				speed = Math.round(member.getSpeed() * 3600)
						+ IMDroid.getContext().getString(
								R.string.team_map_speed_2);

			text.append(sdist + "," + speed + "");
			//++i;
		} else {
			text.append("N/A");
		}
		text.append(")\n");

		return text.toString();
	}

	/**
	 * Gets distance in meters
	 * 
	 * @param lat1
	 *            the lat1
	 * @param lon1
	 *            the lon1
	 * @param lat2
	 *            the lat2
	 * @param lon2
	 *            the lon2
	 * @return Gets distance in meters
	 */
	public static double getDistance(double lat1, double lon1, double lat2,
			double lon2) {
		double R = 6371; // km
		double dLat = Math.toRadians(lat2 - lat1);
		double dLon = Math.toRadians(lon2 - lon1);
		double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
				+ Math.cos(Math.toRadians(lat1))
				* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
				* Math.sin(dLon / 2);
		double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		return R * c * 1000;
	}

	/**
	 * Get the histrocal teams
	 * 
	 * @return
	 */
	public static Collection<Team> getHistoricalTeams() {
		Collection<Team> hisTeams = new ArrayList<Team>();
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(IMDroid.getContext());
		String team1 = prefs.getString("his_team1", null);
		String team2 = prefs.getString("his_team2", null);
		String team3 = prefs.getString("his_team3", null);
		String team4 = prefs.getString("his_team4", null);
		String team5 = prefs.getString("his_team5", null);

		if (team1 != null && team1.length() > 0) {
			Team t = Team.getTeam(team1);
			t.setTeamSource(Team.SOURCE_SEARCH);
			hisTeams.add(t);
		}
		if (team2 != null && team2.length() > 0) {
			Team t = Team.getTeam(team2);
			t.setTeamSource(Team.SOURCE_SEARCH);
			hisTeams.add(t);
		}
		if (team3 != null && team3.length() > 0) {
			Team t = Team.getTeam(team3);
			t.setTeamSource(Team.SOURCE_SEARCH);
			hisTeams.add(t);
		}
		if (team4 != null && team4.length() > 0) {
			Team t = Team.getTeam(team4);
			t.setTeamSource(Team.SOURCE_SEARCH);
			hisTeams.add(t);
		}
		if (team5 != null && team5.length() > 0) {
			Team t = Team.getTeam(team5);
			t.setTeamSource(Team.SOURCE_SEARCH);
			hisTeams.add(t);
		}

		return hisTeams;
	}

	/**
	 * Add the thistrical team list.
	 * 
	 * @param team
	 *            the team
	 */
	public static void addHistricalTeams(Team team) {
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(IMDroid.getContext());
		Editor editor = prefs.edit();
		// 如果不是进入自己的队伍
		if (!team.toString().equals(team)) {
			int index = inHistricalTeams(team);
			// 如果队伍不在历史队伍里面
			if (index <= 0) {
				for (int i = 5; i >= 1; i--) {
					String t = prefs.getString("his_team" + i, null);
					if (t == null)
						continue;

					int j = i + 1;
					editor.putString("his_team" + j, t);
				}
				editor.putString("his_team1", team.toString());
			} else {
				if (index != 1) {
					for (int i = index; i >= 1; i--) {
						int j = i - 1;
						String t = prefs.getString("his_team" + j, null);
						if (t == null)
							continue;
						editor.putString("his_team" + i, t);
					}
					editor.putString("his_team1", team.toString());
				}
			}
		}
		editor.commit();
	}

	/**
	 * The target team is historical team.
	 * 
	 * @param team
	 *            the target team
	 * @return the index of the share preferences , -1 means that it is not in
	 *         the histrical team
	 */
	private static int inHistricalTeams(Team team) {
		for (int i = 1; i <= 5; ++i) {
			SharedPreferences prefs = PreferenceManager
					.getDefaultSharedPreferences(IMDroid.getContext());

			String teamString = prefs.getString("his_team" + i, null);
			if (teamString != null && teamString.equals(team.toString()))
				return i;
		}
		return -1;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return this.getTeamId() + ":" + this.getTeamName() + ":0";
	}
}
